home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 22
/
AACD 22.iso
/
AACD
/
Resources
/
Sound
/
AHI
/
Developer
/
examples
/
Low-level
/
SimplePlay
/
SimplePlay.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-04-23
|
11KB
|
396 lines
/* Simple sample player for AHI using the low-level API.
Hardcoded sample names.
This software is Public Domain. */
#include <devices/ahi.h>
#include <exec/exec.h>
#include <proto/ahi.h>
#include <proto/dos.h>
#include <proto/exec.h>
#define USE_AHI_V4 TRUE
#define CHANNELS 2
#define MAXSAMPLES 16
#define INT_FREQ 50
char *ID = "$VER: SimplePlay 1.3 (23.4.97)\r\n";
APTR samples[MAXSAMPLES] = { 0 };
struct {
BOOL FadeVolume;
Fixed Volume;
sposition Position;
} channelstate[CHANNELS];
struct {
struct AHIEffDSPMask mask;
UBYTE mode[CHANNELS];
} maskeffect = {0};
struct AHIDSPEcho echoeffect = {0};
struct Library *AHIBase;
struct MsgPort *AHImp = NULL;
struct AHIRequest *AHIio = NULL;
BYTE AHIDevice = -1;
struct AHIAudioCtrl *actrl = NULL;
LONG mixfreq = 0;
/* Prototypes */
BOOL OpenAHI(void);
void CloseAHI(void);
BOOL AllocAudio(void);
void FreeAudio(void);
UWORD LoadSample(unsigned char * , ULONG );
void UnloadSample(UWORD );
int main(void);
/******************************************************************************
** PlayerFunc *****************************************************************
******************************************************************************/
__asm __interrupt __saveds static void PlayerFunc(
register __a0 struct Hook *hook,
register __a2 struct AHIAudioCtrl *actrl,
register __a1 APTR ignored) {
int i;
for(i = 0; i < CHANNELS; i++) {
if(channelstate[i].FadeVolume) {
channelstate[i].Volume = (channelstate[i].Volume * 90) / 100; // Fade volume
if(channelstate[i].Volume == 0) {
channelstate[i].FadeVolume = FALSE;
}
AHI_SetVol(i, channelstate[i].Volume, channelstate[i].Position,
actrl, AHISF_IMM);
}
}
return;
}
struct Hook PlayerHook = {
0,0,
(ULONG (* )()) PlayerFunc,
NULL,
NULL,
};
/******************************************************************************
**** OpenAHI ******************************************************************
******************************************************************************/
/* Open the device for low-level usage */
BOOL OpenAHI(void) {
if(AHImp = CreateMsgPort()) {
if(AHIio = (struct AHIRequest *)CreateIORequest(
AHImp,sizeof(struct AHIRequest))) {
#if USE_AHI_V4
AHIio->ahir_Version = 4;
#else
AHIio->ahir_Version = 2;
#endif
if(!(AHIDevice = OpenDevice(AHINAME, AHI_NO_UNIT,
(struct IORequest *) AHIio,NULL))) {
AHIBase = (struct Library *) AHIio->ahir_Std.io_Device;
return TRUE;
}
}
}
FreeAudio();
return FALSE;
}
/******************************************************************************
**** CloseAHI *****************************************************************
******************************************************************************/
/* Close the device */
void CloseAHI(void) {
if(! AHIDevice)
CloseDevice((struct IORequest *)AHIio);
AHIDevice=-1;
DeleteIORequest((struct IORequest *)AHIio);
AHIio=NULL;
DeleteMsgPort(AHImp);
AHImp=NULL;
}
/******************************************************************************
**** AllocAudio ***************************************************************
******************************************************************************/
/* Ask user for an audio mode and allocate it */
BOOL AllocAudio(void) {
struct AHIAudioModeRequester *req;
BOOL rc = FALSE;
req = AHI_AllocAudioRequest(
AHIR_PubScreenName, NULL,
AHIR_TitleText, "Select a mode and rate",
AHIR_DoMixFreq, TRUE,
TAG_DONE);
if(req) {
if(AHI_AudioRequest(req, TAG_DONE)) {
actrl = AHI_AllocAudio(
AHIA_AudioID, req->ahiam_AudioID,
AHIA_MixFreq, req->ahiam_MixFreq,
AHIA_Channels, CHANNELS,
AHIA_Sounds, MAXSAMPLES,
AHIA_PlayerFunc, &PlayerHook,
AHIA_PlayerFreq, INT_FREQ<<16,
AHIA_MinPlayerFreq, INT_FREQ<<16,
AHIA_MaxPlayerFreq, INT_FREQ<<16,
TAG_DONE);
if(actrl) {
// Get real mixing frequency
AHI_ControlAudio(actrl, AHIC_MixFreq_Query, &mixfreq, TAG_DONE);
rc = TRUE;
}
}
AHI_FreeAudioRequest(req);
}
return rc;
}
/******************************************************************************
**** FreeAudio ****************************************************************
******************************************************************************/
/* Release the audio hardware */
void FreeAudio() {
AHI_FreeAudio(actrl);
actrl = NULL;
}
/******************************************************************************
**** LoadSample ***************************************************************
******************************************************************************/
/* Load a (raw) 8 or 16 bit sample from disk. The sample ID is returned
(or AHI_NOSOUND on error). */
UWORD LoadSample(char *filename, ULONG type) {
struct AHISampleInfo sample;
APTR *samplearray = samples;
UWORD id = 0, rc = AHI_NOSOUND;
BPTR file;
// Find a free sample slot
while(*samplearray) {
id++;
samplearray++;
if(id >= MAXSAMPLES) {
return AHI_NOSOUND;
}
}
file = Open(filename, MODE_OLDFILE);
if(file) {
int length;
Seek(file, 0, OFFSET_END);
length = Seek(file, 0, OFFSET_BEGINNING);
*samplearray = AllocVec(length, MEMF_PUBLIC);
if(*samplearray) {
Read(file, *samplearray, length);
sample.ahisi_Type = type;
sample.ahisi_Address = *samplearray;
#if USE_AHI_V4
sample.ahisi_Length = length / AHI_SampleFrameSize(type);
#else
sample.ahisi_Length = length / (type == AHIST_M16S ? 2 : 1);
#endif
if(! AHI_LoadSound(id, AHIST_SAMPLE, &sample, actrl)) {
rc = id;
}
}
Close(file);
}
return rc;
}
/******************************************************************************
**** UnloadSample *************************************************************
******************************************************************************/
void UnloadSample(UWORD id) {
AHI_UnloadSound(id, actrl);
FreeVec(samples[id]);
samples[id] = NULL;
}
/******************************************************************************
**** main *********************************************************************
******************************************************************************/
int main() {
UWORD sample, ahem, louise;
int i;
for(i = 0; i < CHANNELS; i++) {
channelstate[i].FadeVolume = FALSE;
}
if(OpenAHI()) {
if(AllocAudio()) {
ahem = LoadSample("Projekt:ahi/samples/ASS-14.sb", AHIST_M8S);
louise = LoadSample("Projekt:ahi/samples/LouiseR.sw", AHIST_M16S);
if((ahem != AHI_NOSOUND) && (louise != AHI_NOSOUND)) {
// Start feeding samples to sound hardware
if(!(AHI_ControlAudio(actrl,
AHIC_Play, TRUE,
TAG_DONE)))
{
#if USE_AHI_V4
Printf("Playing two samples, one with echo and one without.\n");
// Turn on echo on channel 1
// No error checking here, but you should do that.
maskeffect.mask.ahie_Effect = AHIET_DSPMASK;
maskeffect.mask.ahiedm_Channels = CHANNELS;
maskeffect.mode[0] = AHIEDM_DRY;
maskeffect.mode[1] = AHIEDM_WET;
AHI_SetEffect( &maskeffect, actrl );
echoeffect.ahie_Effect = AHIET_DSPECHO;
echoeffect.ahiede_Delay = mixfreq / 4; // 250 ms
echoeffect.ahiede_Feedback = 0x8000; // 50 %
echoeffect.ahiede_Mix = 0x10000; // 100% and...
echoeffect.ahiede_Cross = 0; // ...0% gives faster echo code.
AHI_SetEffect( &echoeffect, actrl );
AHI_Play(actrl,
// A forever-looping sample on channel 0
AHIP_BeginChannel, 0,
AHIP_Freq, 17640,
AHIP_Vol, 0x10000,
AHIP_Pan, 0xc000,
AHIP_Sound, louise,
AHIP_EndChannel, NULL,
// A oneshot sample on channel 1
AHIP_BeginChannel, 1,
AHIP_Freq, 22254,
AHIP_Vol, 0x10000,
AHIP_Pan, 0x4000,
AHIP_Sound, ahem,
AHIP_LoopSound, AHI_NOSOUND,
AHIP_EndChannel, NULL,
TAG_DONE);
#else
Printf("Playing two samples.\n");
// A forever-looping sample on channel 0
AHI_SetFreq(0, 17640, actrl, AHISF_IMM);
AHI_SetVol(0, 0x10000, 0xc000, actrl, AHISF_IMM);
AHI_SetSound(0, louise, 0, 0, actrl, AHISF_IMM);
// A oneshot sample on channel 1
AHI_SetFreq(1, 22254, actrl, AHISF_IMM);
AHI_SetVol(1, 0x10000, 0x4000, actrl, AHISF_IMM);
AHI_SetSound(1, ahem, 0, 0, actrl, AHISF_IMM);
AHI_SetSound(1, AHI_NOSOUND, 0, 0, actrl, 0);
#endif
channelstate[0].Volume = 0x10000;
channelstate[0].Position = 0xc000;
channelstate[1].Volume = 0x10000;
channelstate[1].Position = 0x4000;
// Wait 5 seconds
Delay(5 * TICKS_PER_SECOND);
#if USE_AHI_V4
Printf("Turning on echo on channel 0.\n");
// Turn on echo on channel 0, turn off channel 1
// No error checking here, but you should do that.
maskeffect.mode[0] = AHIEDM_WET;
maskeffect.mode[1] = AHIEDM_DRY;
AHI_SetEffect( &maskeffect, actrl );
#endif
// Wait 5 seconds
Delay(5 * TICKS_PER_SECOND);
Printf("Fading away the sound on channel 0... ");
Flush(Output());
// Fade away channel 0
channelstate[0].FadeVolume = TRUE;
while(channelstate[0].FadeVolume) {
Delay(1);
}
Printf("Done!\n");
// Wait a sec...
Delay(TICKS_PER_SECOND);
// Stop sounds
AHI_ControlAudio(actrl,
AHIC_Play, FALSE,
TAG_DONE);
#if USE_AHI_V4
// Cancel effects
maskeffect.mask.ahie_Effect = AHIET_DSPMASK | AHIET_CANCEL;
AHI_SetEffect( &maskeffect, actrl );
echoeffect.ahie_Effect = AHIET_DSPECHO | AHIET_CANCEL;
AHI_SetEffect( &echoeffect, actrl );
#endif
}
}
// Ask AHI to unload all loaded samples and free the memory for them
for(sample = 0; sample < MAXSAMPLES; sample++) {
UnloadSample(sample);
}
}
FreeAudio();
}
CloseAHI();
return 0;
}